package com.example.dragdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ScrollView;
import android.widget.Scroller;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.customview.widget.ViewDragHelper;

/**
 * @ProjectName: DragDemo
 * @Package: com.example.dragdemo
 * @ClassName: DragLayout
 * @Description: java类作用描述
 * @Author: 作者名
 * @CreateDate: 2021/8/13 9:53
 * @UpdateUser: 更新者：
 * @UpdateDate: 2021/8/13 9:53
 * @UpdateRemark: 更新说明：
 * @Version: 1.0
 */
public class DragLayout extends FrameLayout {
    private ViewDragHelper mViewDragHelper;
    private boolean mIsExpand = false;//是否展开
    private int mMaxExpandOffset = 1400;//最大展开距离
    private int mExpandOffset = 300;//可以触发展开或收起所滑动的最小距离
    private View mScrollView;//滑动的View
    private ScrollProgressListener scrollProgressListener;
    private boolean isScroll = false;//当前需要滑动的控件是否正在滑动

    public ScrollProgressListener getScrollProgressListener() {
        return scrollProgressListener;
    }

    public void setScrollProgressListener(ScrollProgressListener scrollProgressListener) {
        this.scrollProgressListener = scrollProgressListener;
    }

    public DragLayout(Context context) {
        this(context,null);
    }

    public DragLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public DragLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        mViewDragHelper = ViewDragHelper.create(this, 1f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(@NonNull View child, int pointerId) {
                //需要滑动的子控件就返回true（这里我们通过id来规定的）
                isScroll = true;
                return child.getId() == R.id.scroll_container;
            }
            @Override
            public int clampViewPositionHorizontal(@NonNull View child, int left, int dx) {
                return 0;
            }
            @Override
            public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
                int topVal;
                if(top > mMaxExpandOffset){
                    //当前滑动的控件是需要滑动的控件，如果向下滑动的距离超过了最大的展开距离那就返回设置的最大距离
                    topVal = mMaxExpandOffset;
                }else if(top > 0){
                    //当前滑动的控件是需要滑动的控件，如果向下滑动的距离没超过最大的展开距离那就按手指的拖动进行移动
                    topVal = top;
                }else {
                    //滑动距离小于0的时候就返回0（即不动）
                    topVal = 0;
                }
                if(scrollProgressListener != null){
                    scrollProgressListener.onScroll(mMaxExpandOffset,topVal);
                }
                return topVal;
            }

            @Override
            public int getViewVerticalDragRange(@NonNull View child) {
                //默认为0，我们这里需要将它设置为1
                return 1;
            }

            @Override
            public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
                isScroll = false;
                if(mIsExpand){
                    if(mMaxExpandOffset - releasedChild.getTop() >= mExpandOffset){
                        //已经展开设置关闭
                        mIsExpand = false;
                        mViewDragHelper.smoothSlideViewTo(releasedChild,0,0);
                    }else {
                        mViewDragHelper.smoothSlideViewTo(releasedChild,0,mMaxExpandOffset);
                    }
                }else {
                    if(releasedChild.getTop() >= mExpandOffset){
                        //没有展开，设置展开
                        mIsExpand = true;
                        mViewDragHelper.smoothSlideViewTo(releasedChild,0,mMaxExpandOffset);
                    }else {
                        mViewDragHelper.smoothSlideViewTo(releasedChild,0,0);
                    }
                }
                invalidate();
            }
        });
    }

    @Override
    public void computeScroll() {
        if(mViewDragHelper != null && mViewDragHelper.continueSettling(true)){
            if(scrollProgressListener != null && mScrollView != null){
                scrollProgressListener.onScroll(mMaxExpandOffset,mScrollView.getTop());
            }
            invalidate();
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        //存储滑动的子控件
        if(mScrollView == null){
            for (int i = 0; i < getChildCount(); i++) {
                View childAt = getChildAt(i);
                if(childAt.getId() == R.id.scroll_container){
                    mScrollView = childAt;
                    break;
                }
            }
        }
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        //子控件如果是ScrollView的话就判断是否触顶，如果不是在顶部就按默认的方式处理，不让ViewDragHelper处理
        if(mScrollView != null && mScrollView instanceof ScrollView && mScrollView.getScrollY() != 0){
            return super.onInterceptTouchEvent(ev);
        }
        return mViewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mViewDragHelper.processTouchEvent(event);
        //这里根据判断当前是否正在滑动需要滑动的子控件，如果不是的话就不消费事件，而让它回传到父级，否则地图就划不动了
        return isScroll || super.onTouchEvent(event);
    }

    /**
     * 滑动的进度回调
     */
    public interface ScrollProgressListener{
        /**
         *
         * @param maxOffset 最大的展开的值
         * @param scrollVal 当前距离顶部的值
         */
        void onScroll(int maxOffset,int scrollVal);
    }
}
